/*
*
* ████████╗░█████╗░███████╗██████╗░░█████╗░
* ╚══██╔══╝██╔══██╗██╔════╝██╔══██╗██╔══██╗
* ░░░██║░░░██║░░██║█████╗░░██████╦╝███████║
* ░░░██║░░░██║░░██║██╔══╝░░██╔══██╗██╔══██║
* ░░░██║░░░╚█████╔╝██║░░░░░██████╦╝██║░░██║
* ░░░╚═╝░░░░╚════╝░╚═╝░░░░░╚═════╝░╚═╝░░╚═╝
* 
*  :: 九方通逊-Henry ::   Copyright©2020 tofba.com  
* 
*/
package com.lmexpress.service.impl;

import java.io.File;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;
import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import com.lmexpress.enums.ApiCredential;
import com.lmexpress.enums.ApiOrderError;
import com.lmexpress.enums.LabelSuffix;
import com.lmexpress.orm.eccang.Consignee;
import com.lmexpress.orm.eccang.Item;
import com.lmexpress.orm.eccang.Shipper;
import com.lmexpress.orm.eccang.YCOrder;
import com.lmexpress.orm.openapi.ExpressOrderApi;
import com.lmexpress.orm.openapi.OrderInvoice;
import com.lmexpress.orm.rest.ApiLabelResponse;
import com.lmexpress.orm.rest.ApiOrderResponse;
import com.lmexpress.service.ApiService;
import com.lmexpress.util.ApiUtil;
import com.lmexpress.util.HttpClientPoolUtil;
import com.lmexpress.util.HttpClientResult;
import com.lmexpress.util.PropertiesUtil;

/**
 * 
 * <易仓API>
 * 
 * @author Henry(fba02)
 * @version [版本号, 2020-12-09]
 * @see [相关类/方法]
 * @since [产品/模块版本]
 */
public class EcCangClient implements ApiService {
    private static final Logger LOGGER = LoggerFactory.getLogger(EcCangClient.class);
    
    @Override
    public ApiOrderResponse preProcessCreateOrder(ExpressOrderApi expressOrderApi) {
        return null;
    }
    
    @Override
    public String mapping(ExpressOrderApi expressOrderApi) {
        YCOrder ycOrder = new YCOrder();
        ycOrder.setReference_no(expressOrderApi.getCustomerInvoiceCode());
        // 第三方渠道代码
        Map<String, String> apiCredentials = expressOrderApi.getApiCredentials();
        ycOrder.setShipping_method(apiCredentials.get(ApiCredential.ECCANG_PRODUCTCODE.getKey()));
        ycOrder.setCountry_code(expressOrderApi.getCountryCode());
        ycOrder.setOrder_weight(expressOrderApi.getWeight());
        ycOrder.setOrder_pieces(expressOrderApi.getOrderPiece());
        ycOrder.setIs_return((StringUtils.isNotBlank(expressOrderApi.getReturnSign()) && RETURN_SIGN_YES.equals(expressOrderApi.getReturnSign())) ? 1 : 0);
        
        Consignee consignee = new Consignee();
        consignee.setConsignee_company(expressOrderApi.getConsigneeCompanyName());
        consignee.setConsignee_province(expressOrderApi.getConsigneeState());
        consignee.setConsignee_city(expressOrderApi.getConsigneeCity());
        consignee.setConsignee_street(expressOrderApi.getConsigneeAddress());
        consignee.setConsignee_postcode(expressOrderApi.getConsigneePostCode());
        consignee.setConsignee_name(expressOrderApi.getConsigneeName());
        consignee.setConsignee_telephone(expressOrderApi.getConsigneeTelephone());
        consignee.setConsignee_mobile(expressOrderApi.getConsigneeMobile());
        consignee.setConsignee_email(expressOrderApi.getConsigneeEmail());
        ycOrder.setConsignee(consignee);
        
		Shipper shipper = new Shipper();
		if (DEFAULT_SHIPPER.equals(ApiCredential.ECCANG_DEFAULT_SHIPPER.getKey())) {
			shipper.setShipper_company(PropertiesUtil.getProperty("lm.shipper.company"));
			shipper.setShipper_countrycode(PropertiesUtil.getProperty("lm.shipper.country"));
			shipper.setShipper_province(PropertiesUtil.getProperty("lm.shipper.province"));
			shipper.setShipper_city(PropertiesUtil.getProperty("lm.shipper.city"));
			shipper.setShipper_street(PropertiesUtil.getProperty("lm.shipper.address_all"));
			shipper.setShipper_postcode(PropertiesUtil.getProperty("lm.shipper.zipcode"));
			shipper.setShipper_name(PropertiesUtil.getProperty("lm.shipper.name"));
			shipper.setShipper_telephone(PropertiesUtil.getProperty("lm.shipper.phone"));
			shipper.setShipper_mobile(PropertiesUtil.getProperty("lm.shipper.mobile"));
		} else {
			shipper.setShipper_company(expressOrderApi.getShipperCompanyName());
			shipper.setShipper_countrycode(StringUtils.isBlank(expressOrderApi.getShipperCountry()) ? DEFAULT_SHIPPER_COUNTRY_CODE : expressOrderApi.getShipperCountry());
			shipper.setShipper_province(expressOrderApi.getShipperState());
			shipper.setShipper_city(expressOrderApi.getShipperCity());
			shipper.setShipper_street(expressOrderApi.getShipperAddress1());
			shipper.setShipper_postcode(expressOrderApi.getShipperPostCode());
			shipper.setShipper_name(expressOrderApi.getShipperName());
			shipper.setShipper_telephone(expressOrderApi.getShipperTelephone());
			shipper.setShipper_mobile(expressOrderApi.getShipperTelephone());
		}
		ycOrder.setShipper(shipper);
        
        List<OrderInvoice> orderInvoices = expressOrderApi.getOrderInvoices();
        Double totalWeight = 0D;
        List<Item> items = new ArrayList<Item>();
        Item item = null;
        for (OrderInvoice orderInvoice : orderInvoices) {
            item = new Item();
            item.setInvoice_enname(orderInvoice.getSkuNameEn());
            item.setInvoice_cnname(orderInvoice.getSkuNameCn());
            item.setInvoice_weight(orderInvoice.getInvoiceWeight());
            item.setInvoice_quantity(orderInvoice.getInvoicePcs());
            item.setInvoice_unitcharge(orderInvoice.getInvoiceAmount());
            item.setHs_code(orderInvoice.getHsCode());
            item.setInvoice_note(orderInvoice.getInvoicePurpose());
            item.setSku(orderInvoice.getSkuCode());
            if (null != orderInvoice.getInvoiceWeight()) {
                totalWeight += orderInvoice.getInvoiceWeight();
            } else {
                item.setInvoice_weight(expressOrderApi.getWeight() / orderInvoices.size());
            }
            items.add(item);
        }
        if (null == ycOrder.getOrder_weight() || (ycOrder.getOrder_weight() != null && ycOrder.getOrder_weight() < 0.0001)) {
            ycOrder.setOrder_weight(totalWeight);
        }
        ycOrder.setItemArr(items);
        return new Gson().toJson(ycOrder);
    }
    
    @Override
	public ApiOrderResponse createOrder(ExpressOrderApi expressOrderApi) {
		try {
			String orderJson = mapping(expressOrderApi);
			LOGGER.info("eccang.shipment.request:{}", orderJson);
			Map<String, String> apiCredentials = expressOrderApi.getApiCredentials();
			String xml = buildRequst(orderJson, apiCredentials.get(ApiCredential.ECCANG_TOKEN.getKey()), apiCredentials.get(ApiCredential.ECCANG_KEY.getKey()), ApiCredential.ECCANG_ORDER.getValue());
			// String responseXml =
			// SendUrl.sendPost(configureMap.get(ApiConfigure.ECCANG_URL.getKey()), xml);//
			// "http://120.79.51.80/default/svc/web-service"
			HttpClientResult httpClientResult = HttpClientPoolUtil.doPost(apiCredentials.get(ApiCredential.ECCANG_URL.getKey()), HttpClientPoolUtil.setXmlHeader(), xml, false);
			if (httpClientResult == null || (null != httpClientResult && StringUtils.isBlank(httpClientResult.getContent()))) {
				return new ApiOrderResponse(false, null, ApiOrderError.SERVICE_NO_DATA_RETURN.getMessage(), true, null);
			}
			String responseXml = httpClientResult.getContent();
			if (StringUtils.isBlank(responseXml)) {
				return new ApiOrderResponse(false, null, ApiOrderError.SERVICE_NO_DATA_RETURN.getMessage(), true, null);
			}
			LOGGER.info("eccang.shipment.response:{}", responseXml);
			Document document = DocumentHelper.parseText(responseXml); // 将字符串转为XML
			Element rootElement = document.getRootElement(); // 获取根节点
			String rootResponse = rootElement.getStringValue();
			if (StringUtils.isBlank(rootResponse)) {
				return new ApiOrderResponse(false, null, ApiOrderError.SERVICE_NO_DATA_RETURN.getMessage(), true, null);
			}
			Map<String, Object> rootResponseMap = new Gson().fromJson(rootResponse, new TypeToken<Map<String, Object>>() {
			}.getType());
			String ask = (String) rootResponseMap.get("ask");
			if (!DEFAULT_SUCCESS.equalsIgnoreCase(ask)) {
				@SuppressWarnings("unchecked")
				Map<String, Object> errorMap = (Map<String, Object>) rootResponseMap.get("Error");
				String errMessage = (String) errorMap.get("errMessage");
				return new ApiOrderResponse(false, null, errMessage, false, rootResponse);
			}
			String shipping_method_no = (String) rootResponseMap.get("shipping_method_no");
			String order_code = (String) rootResponseMap.get("order_code");
			ApiOrderResponse apiOrderResponse = new ApiOrderResponse();
			apiOrderResponse.setSuccess(true);
			apiOrderResponse.setReferenceNo(expressOrderApi.getCustomerInvoiceCode());
			apiOrderResponse.setOriginalResponse(rootResponse);
			apiOrderResponse.setThirdPartyorderNo(order_code);
			apiOrderResponse.setTrackNumber(shipping_method_no);
			ApiLabelResponse apiLabelResponse = label(expressOrderApi.getCustomerInvoiceCode(), apiCredentials);
			if (StringUtils.isNotBlank(apiLabelResponse.getLabelPath())) {
				apiOrderResponse.setLabelUrl(apiLabelResponse.getLabelPath());
				apiOrderResponse.setLmLabelUrl(apiLabelResponse.getRelativePath());
			}
			return apiOrderResponse;
		} catch (Exception e) {
			LOGGER.error("eccang.shipment.exception", e);
			return new ApiOrderResponse(false, null, ApiOrderError.CREATE_ORDER_EXCEPTION.getMessage(), false, e.getMessage());
		}
	}
    
    @Override
    public ApiLabelResponse label(String referenceNo, Map<String, String> apiCredentials) {
        try {
            String xml = buildRequst("{\"reference_no\":\"" + referenceNo + "\"}", apiCredentials.get(ApiCredential.ECCANG_TOKEN.getKey()), apiCredentials.get(ApiCredential.ECCANG_KEY.getKey()), ApiCredential.ECCANG_LABEL.getValue());
            HttpClientResult httpClientResult = HttpClientPoolUtil.doPost(apiCredentials.get(ApiCredential.ECCANG_URL.getKey()), HttpClientPoolUtil.setXmlHeader(), xml, false);
            if (httpClientResult == null || (null != httpClientResult && StringUtils.isBlank(httpClientResult.getContent()))) {
                return new ApiLabelResponse(referenceNo, null);
            }
            String responseXml = httpClientResult.getContent();
            LOGGER.info("eccang.label.response:{}", responseXml);
            Document document = DocumentHelper.parseText(responseXml); // 将字符串转为XML
            Element rootElement = document.getRootElement(); // 获取根节点
            String rootResponse = rootElement.getStringValue();
            if (StringUtils.isBlank(rootResponse)) {
                return new ApiLabelResponse(referenceNo, null);
            }
            Map<String, Object> rootResponseMap = new Gson().fromJson(rootResponse, new TypeToken<Map<String, Object>>() {
            }.getType());
            String ask = (String)rootResponseMap.get("ask");
            if (DEFAULT_SUCCESS.equalsIgnoreCase(ask)) {
                ApiLabelResponse apiLabelResponse = new ApiLabelResponse();
                apiLabelResponse.setBarCode(referenceNo);
                String url = (String)rootResponseMap.get("url");
                String pdfName = referenceNo + LabelSuffix.PDF.getSuffix();
                // 当前月份
                String centrePath = ApiUtil.getCurrentDay() + File.separator;
                String relativePath = DEFAULT_LABEL_FOLDER + File.separator + centrePath;
                String folderPath = DEFAULT_LABEL_ROOT + relativePath;
                if (!new File(folderPath).exists()) {
                    new File(folderPath).mkdirs();
                }
                String fileUrl = folderPath + pdfName;
                try {
                    FileUtils.copyURLToFile(new URL(url), new File(fileUrl));// 下载面单到本地
                    apiLabelResponse.setRelativePath(relativePath + pdfName);
                } catch (Exception e) {
                    LOGGER.error("eccang.copy.url.to.file.exception", e);
                }
                apiLabelResponse.setLabelPath(url);
                return apiLabelResponse;
            }
            return new ApiLabelResponse(referenceNo, null);
        } catch (Exception e) {
            LOGGER.error("eccang.label.exception", e);
            return new ApiLabelResponse(referenceNo, null);
        }
    }
    
    @Override
    public void tracking(String trackNumber, Map<String, String> configureMap) {
        
    }
    
    @Override
    public String trackNumber(String code, Map<String, String> configureMap) {
        return null;
    }
    
    @Override
    public ApiLabelResponse labelRender(String trackNumber, ExpressOrderApi expressOrderApi) {
        return null;
    }
    
    /**
     * 
     * <构建请求XML>
     * 
     * @param paramsJson JSON字符串
     * @param appToken
     * @param appKey
     * @param service
     * @return
     * @author Henry(fba02)
     * @version [版本号, 2020-10-16]
     * @see [类、类#方法、类#成员]
     */
    private static String buildRequst(String paramsJson, String appToken, String appKey, String service) {
        StringBuilder soapBuilder = new StringBuilder();
        soapBuilder.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
        soapBuilder.append("<SOAP-ENV:Envelope xmlns:SOAP-ENV=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:ns1=\"http://www.example.org/Ec/\">");
        soapBuilder.append("    <SOAP-ENV:Body>");
        soapBuilder.append("        <ns1:callService>");
        soapBuilder.append("            <paramsJson>" + paramsJson + "</paramsJson>");
        soapBuilder.append("            <appToken>" + appToken + "</appToken>");
        soapBuilder.append("            <appKey>" + appKey + "</appKey>");
        soapBuilder.append("            <service>" + service + "</service>");
        soapBuilder.append("        </ns1:callService>");
        soapBuilder.append("    </SOAP-ENV:Body>");
        soapBuilder.append("</SOAP-ENV:Envelope>");
        return soapBuilder.toString();
    }
    
    public static void main(String[] args) {
        String xml = buildRequst("{\"reference_no\":\"TOFBA202010121101\"}", "a309555234c953fe5acbd14d9eb99fca", "a309555234c953fe5acbd14d9eb99fca53a7d8f491bcd222201add4900a83fa0", "getLabelUrl");
        System.out.println(xml);
        try {
            HttpClientResult httpClientResult = HttpClientPoolUtil.doPost("http://120.79.51.80/default/svc/web-service", HttpClientPoolUtil.setXmlHeader(), xml, false);
            System.out.println(httpClientResult.getContent());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public ApiLabelResponse label(String referenceNo, String trackNumber, Map<String, String> configureMap) {
        return null;
    }
}